package homework_2;

import java.awt.image.BufferedImage;
import javax.imageio.*;
import java.io.File;
import java.io.IOException; 
public class BilinearInterpolationImageScaleFliter extends ImageFliter {
	/*
	 * This mathod is uesd to zoom in or zoom out a picture, which is 
	 * based on Bilinear Interpolation.
	 * When 0 < widthScale, heightScale < 1 , the picture will be zoomed in.
	 * When 1 < widthScale, heightScale, the picture will be zoomed out.
	 * PNG, JPG AND BMP ONLY 
	 */
	@Override
	public BufferedImage imageScale(String pathName, float widthScale, float heightScale) throws IOException {
		if (!pathName.endsWith("png") && !pathName.endsWith("jpg") && !pathName.endsWith("bmp")) {
			throw new RuntimeException("Wrrong File!");
		}
		File file = new File(pathName);
		BufferedImage bufferedImage = ImageIO.read(file);
		widthScale = 1/widthScale;
		heightScale = 1/heightScale;
		
		int srcW = bufferedImage.getWidth();
		int srcH = bufferedImage.getHeight();
		int destW = (int)(bufferedImage.getWidth() / widthScale);
		int destH = (int)(bufferedImage.getHeight() / heightScale);
		
		int[] inPixels = bufferedImage.getRGB(0, 0, srcW, srcH, null, 0, srcW);
		int[] outPixels = new int[destW * destH];
		
		for(int row = 0; row < destH; row++) {
			
			double x = row * heightScale;
			double j = Math.floor(x);
			double t = x - j;
			
			for (int col = 0; col < destW; col++) {
				double y = col * widthScale;
				double k = Math.floor(y);
				double u = y - k;
				
				double[] elements = new double[4]; 
				elements[0] = (1 - t) * (1 - u);
				elements[1] = t * (1 - u);
				elements[2] = t * u;
				elements[3] = (1 - t) * u;
				
				int[] pargb = {0, 0, 0, 0};
				
				int[] pixel = new int[4];
				pixel[0] = inPixels[getClip((int)j, srcH - 1, 0) * srcW + getClip((int)k, srcW - 1, 0)];
				pixel[1] = inPixels[getClip((int)j + 1, srcH - 1, 0) * srcW + getClip((int)k, srcW - 1, 0)];
				pixel[2] = inPixels[getClip((int)j + 1, srcH - 1, 0) * srcW + getClip((int)k + 1, srcW - 1, 0)];
				pixel[3] = inPixels[getClip((int)j, srcH - 1, 0) * srcW + getClip((int)k + 1, srcW - 1, 0)];
				for (int m = 0; m < 4; m++) {
					for (int n = 0; n < 4; n++) {
						pargb[m] += (int)(elements[n] * ((pixel[n] >> 24 - 8 * m) & 0xff));
					}
				}
				outPixels[row * destW + col] = (pargb[0] << 24) |
						(pargb[1] << 16) |
						(pargb[2] << 8) |
						pargb[3];
				
			}
		}
		BufferedImage bufImg = new BufferedImage(destW, destH,
				pathName.endsWith("png") ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
		
		bufImg.setRGB(0, 0, destW, destH, outPixels, 0, destW);
		return bufImg;
	}
	private int getClip(int x, int max, int min) {
		return x > max ? max : x > min ? x : min;
	}
}
